﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Net.Messgae;
using pbc = global::Google.Protobuf.Collections;
using MatchCore;

public class BattleController : MonoBehaviour, IGameEventer
{
    public ControllerManager controllerManager;
    public BattleGameObjManager battleGameObjManager;

    private RoomInfo _roomInfo;

    class Loger : ILoger
    {
        public void LogException(string text)
        {
            Debug.LogError(text);
        }

        public void LogDebug(string text)
        {
            Debug.Log(text);
        }

        public void LogError(string text)
        {
            Debug.LogError(text);
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        controllerManager.SetEnable(false);

        if(!Init())
        {
            Warnning.Show("战斗初始化失败",()=>{

                GoHome();

            });
        }
    }   

    void Awake()
    {
        Model.Instance().networkManager.SetTcpDisconnectedEvent(OnDisconnected,true);
        Model.Instance().networkManager.SetUdpErrorEvent(OnUdpError,true);
        Waiting.SetTimeout(OnWaitTimeout,true);

        Model.Instance().msgHandler.SetMsgHandler<MessageNotifyRaceStart>(MessageId.NotifyRaceStart,OnMessageNotifyRaceStart,true);
        Model.Instance().msgHandler.SetMsgHandler<MessageNotifySyncFrames>(MessageId.NotifySyncFrames,OnMessageNotifySyncFrames,true);
        Model.Instance().msgHandler.SetMsgHandler<MessageGetFramesResp>(MessageId.GetFramesResp,OnMessageGetFramesResp,true);
        Model.Instance().msgHandler.SetMsgHandler<MessageEndGameResp>(MessageId.EndGameResp,OnMessageEndGameResp,true);
        Model.Instance().msgHandler.SetMsgHandler<MessageNotifyGameEndFailed>(MessageId.NotifyGameEndFailed,OnMessageNotifyGameEndFailed,true);

        TurnManager.Destroy();

        LogicManager.Instance().SetSceneRect(new MatchCore.Rect(0,0,Config.SCENE_SIZE.x,Config.SCENE_SIZE.y));
        LogicManager.Instance().SetLoger(new Loger());
        LogicManager.Instance().SetGameEventer(this);
        TurnManager.Instance().onPlayStarted = OnPlayStarted;
        TurnManager.Instance().onPlayEnd = OnPlayEnd;
        TurnManager.Instance().onWaiting = OnWaiting;
        TurnManager.Instance().onWaitEnd = OnWaitEnd;
    }

    void OnDestroy()
    {
        Model.Instance().networkManager.SetTcpDisconnectedEvent(OnDisconnected,false);
        Model.Instance().networkManager.SetUdpErrorEvent(OnUdpError,false);
        Waiting.SetTimeout(OnWaitTimeout,false);

        Model.Instance().msgHandler.SetMsgHandler<MessageNotifyRaceStart>(MessageId.NotifyRaceStart,OnMessageNotifyRaceStart,false);
        Model.Instance().msgHandler.SetMsgHandler<MessageNotifySyncFrames>(MessageId.NotifySyncFrames,OnMessageNotifySyncFrames,false);
        Model.Instance().msgHandler.SetMsgHandler<MessageGetFramesResp>(MessageId.GetFramesResp,OnMessageGetFramesResp,false);
        Model.Instance().msgHandler.SetMsgHandler<MessageEndGameResp>(MessageId.EndGameResp,OnMessageEndGameResp,false);
        Model.Instance().msgHandler.SetMsgHandler<MessageNotifyGameEndFailed>(MessageId.NotifyGameEndFailed,OnMessageNotifyGameEndFailed,false);

        TurnManager.Destroy();
    }

    bool Init()
    {
        var roomInfo = Model.Instance().roomModel.roomInfo;
        if(null == roomInfo || null == roomInfo.GameStartInfo)
        {
            Disconnect();

            Debug.LogError("BattleController Start roomInfo is null!");

            return false;
        }

        var serverInfo = roomInfo.GameStartInfo.ServerInfo;

        if(!Model.Instance().networkManager.ConnectUdp(serverInfo.Ip,serverInfo.Port))
        {
            Debug.LogError("BattleController connect failed!");
            
            Disconnect();

            return false;
        }

        _roomInfo = roomInfo;

        MessageRaceHandshake req = new MessageRaceHandshake();
        req.RoomId = _roomInfo.MatchId;
        req.OpenId = Model.Instance().playerModel.playerInfo.OpenId;
        req.Token = _roomInfo.GameStartInfo.Token;
        Model.Instance().msgHandler.SendMessage(MessageId.RaceHandshake,req,true);

        Waiting.SetActive(true,15f);

        return true;
    }

    bool InitMatch()
    {   
        if(!battleGameObjManager.InitObjs())
        {
            return false;
        }

        return true;
    }

    void OnMessageNotifyRaceStart(uint msgID,MessageNotifyRaceStart resp)
    {
        Waiting.SetActive(false);

        if(!InitMatch())
        {
            Disconnect();

            Warnning.Show("初始化比赛失败",()=>{

                GoHome();

            });
            return;
        }

        TurnManager.Instance().SetStartTime((long)resp.StartTime);

        if(0 == resp.CurFrameId)
        {
            TurnManager.Instance().Start();

            Waiting.SetActive(true,15f);
        }
        else
        {
            MessageGetFramesReq req = new MessageGetFramesReq();
            req.RoomId = _roomInfo.MatchId;
            Model.Instance().msgHandler.SendMessage(MessageId.GetFramesReq,req);

            Waiting.SetActive(true,15f);
        }
    }

    void FixedUpdate()
    {
        TurnManager.Instance().Update();
    }

    public void OnGameStarted()
    {
        if(TurnManager.Instance().IsRunning())
        {
            Waiting.SetActive(false);

            controllerManager.SetEnable(true);
        }
    }

    void OnPlayStarted()
    {
        Waiting.SetActive(true,999999f);

        controllerManager.SetEnable(false);

        Debug.Log("OnPlayStarted");
    }
    
    void OnPlayEnd()
    {
        Waiting.SetActive(false);

        controllerManager.SetEnable(true);

        Debug.Log("OnPlayEnd");
    }

    void OnWaiting()
    {
        Waiting.SetActive(true,999999f);

        controllerManager.SetEnable(false);

        Debug.Log("OnWaiting");
    }

    void OnWaitEnd()
    {
        Waiting.SetActive(false);

        controllerManager.SetEnable(true);

        Debug.Log("OnWaitEnd");
    }

    public void OnGameOver()
    {
        Debug.Log("OnGameOver");

        Waiting.SetActive(false);

        controllerManager.SetEnable(false);

        TurnManager.Instance().Stop();

        Model.Instance().networkManager.DisconnectUdp();

        MessageEndGameReq req = new MessageEndGameReq();
        req.RoomId = _roomInfo.MatchId;
        for(int i = 0; i < _roomInfo.players.Count; i++)
        {
            var roomPlayer = _roomInfo.players[i];
            var player = LogicManager.Instance().FindPlayerByIndex(roomPlayer.Index);
            if(player != null)
            {
                var endPlayer = new EndGamePlayerInfo();
                endPlayer.OpenId = roomPlayer.OpenId;
                endPlayer.Index = player.GetIndex();
                endPlayer.Score = (uint)player.GetBlood();
                req.Players.Add(endPlayer);
            }
        }
        Model.Instance().msgHandler.SendMessage(MessageId.EndGameReq,req);

        Waiting.SetActive(true,15f);
    }

    void OnMessageEndGameResp(uint msgID, MessageEndGameResp resp)
    {
        Waiting.SetActive(false);

        if(resp.Result != 0)
        {
            Disconnect();

            Warnning.Show("结束比赛失败" + resp.Result,()=>{

                GoHome();

            });

            return;
        }

        string text = "失败!";
        foreach(var player in resp.Players)
        {
            if(player.OpenId == Model.Instance().playerModel.playerInfo.OpenId)
            {
                if(player.Score > 0)
                {
                    text = "胜利!";
                }
                break;
            }            
        }

        Model.Instance().roomModel.SetRoomInfo(null);

        Warnning.Show(text,()=>{

            SceneHelper.LoadScene("room");

        });
    }

    void OnMessageNotifyGameEndFailed(uint msgID, MessageNotifyGameEndFailed resp)
    {
        Waiting.SetActive(false);

        controllerManager.SetEnable(false);

        TurnManager.Instance().Stop();

        Disconnect();

        Warnning.Show("比赛异常结束" + resp.Result,()=>{

            GoHome();

        });
    }

    void OnMessageNotifySyncFrames(uint msgID, MessageNotifySyncFrames resp)
    {
        foreach(var frame in resp.Frames)
        {
            TurnManager.Instance().AddTurn(frame);

            //Debug.Log("AddTurn " + frame.FrameId);
        }
    }

    void OnMessageGetFramesResp(uint msgID, MessageGetFramesResp resp)
    {
        Waiting.SetActive(false);

        if(resp.Result != 0)
        {
            Disconnect();

            Warnning.Show("追帧失败:" + resp.Result,()=>{

                GoHome();

            });

            return;
        }

        foreach(var frame in resp.Frames)
        {
            TurnManager.Instance().AddTurn(frame);
        }

        TurnManager.Instance().SetPlayGameTick(0);
        TurnManager.Instance().Start();
    }

    void OnWaitTimeout()
    {
        Warnning.Show("网络连接异常",()=>{

            GoHome();

        });

        Disconnect();
    }

    void OnDisconnected()
    {
        Waiting.SetActive(false);

        Disconnect();

        Warnning.Show("连接服务器失败",()=>{

            GoHome();
            
        });
    }   

    void OnUdpError()
    {
        Waiting.SetActive(false);

        Disconnect();

        Warnning.Show("Udp错误",()=>{

            GoHome();
            
        });
    }

    void Disconnect()
    {
        Model.Instance().networkManager.SetTcpDisconnectedEvent(OnDisconnected,false);

        Model.Instance().networkManager.DisconnectTcp();

        Model.Instance().networkManager.DisconnectUdp();

        TurnManager.Instance().Stop();

        controllerManager.SetEnable(false);
    }

    void GoHome()
    {
        SceneHelper.LoadScene("home");
    }
}
